package cn.zk.commom.tcp.obd;

import org.springframework.stereotype.Component;

import java.util.ArrayList;


//基础数据流附表
@Component
public class PositionItemBasicData {
    public final boolean  mIsValid;          //基础数据是否有效

    public final boolean  mIsMileageValid;   //里程数据是否有效
    public final byte mMileageType;          //总里程，算法类型
    public final long mMileageValue;         //总里程，单位:米

    //
    public final boolean  mIsOilConsumptionValid;   //总耗油量是否有效
    public final byte mOilConsumptionType;   //总耗油量，算法类型
    public final long mOilConsumptionValue;  //总耗油量，单位:ML

    //
    public final boolean  mIsRunTimeValid;   //总运行时长是否有效
    public final long mRunTime;              //总运行时长	秒

    public final boolean  mIsFlameOutValid;   //总熄火时长是否有效
    public final long mFlameOutDuration;     //总熄火时长	秒

    public final boolean  mIsIdlingTimeValid;   //总怠速时长是否有效
    public final long mIdlingTime;           //总怠速时长	秒

    //
    public final boolean  mIsAccValid;   //加速度信息是否有效
    public final int   mAccCount;       //加速度表，最近1秒内采集点个数
    public final int   mAccInterval;    //加速度表，最近1秒内采集点间隔,毫秒
    public final int   mAccMaxValue;    //加速度表，1秒内最大加速度值,mg
    public final int[] mAccValue;       //加速度表，N个采集点加速度平均值,mg


    public PositionItemBasicData(byte[] data) {
        ArrayList<byte[]> infos = DataSplitting(data);
        if(infos.size() == 0) {
            mIsValid = false;
            mIsMileageValid = false;
            mMileageType = 0;
            mMileageValue = 0;
            mIsOilConsumptionValid = false;
            mOilConsumptionType = 0;
            mOilConsumptionValue = 0;
            mIsRunTimeValid = false;
            mRunTime = 0;
            mIsFlameOutValid = false;
            mFlameOutDuration = 0;
            mIsIdlingTimeValid = false;
            mIdlingTime = 0;
            mIsAccValid = false;
            mAccCount = 0;
            mAccInterval = 0;
            mAccMaxValue = 0;
            mAccValue = null;
            return;
        }

        //
        boolean isMileageValid = false;
        byte mileageType = 0;
        long mileageValue = 0;
        boolean  isOilConsumptionValid = false;
        byte oilConsumptionType = 0;
        long oilConsumptionValue = 0;
        boolean isRunTimeValid = false;
        long runTime = 0;
        boolean isFlameOutValid = false;
        long flameOutDuration = 0;
        boolean isIdlingTimeValid = false;
        long idlingTime = 0;
        boolean isAccValid = false;
        int accCount = 0;
        int accInterval = 0;
        int accMaxValue = 0;
        int[] accValue = null;

        for(int i = 0; i < infos.size(); ++i)
        {
            byte[] var = infos.get(i);
            int type = (int)ByteArrayToLong(var, 0, 2);
            int len = var[2];

            byte[] sub_data = new byte[len];
            System.arraycopy(var, 3, sub_data, 0, sub_data.length);

            switch (type) {
                case 0x0003: //总里程数据
                    if (len == 5) {
                        isMileageValid = true;
                        mileageType = sub_data[0];
                        mileageValue = ByteArrayToLong(sub_data, 1, 4);
                    }
                    break;

                case 0x0004: //总油耗数据
                    if (len == 5) {
                        isOilConsumptionValid = true;
                        oilConsumptionType = sub_data[0];
                        oilConsumptionValue = ByteArrayToLong(sub_data, 1, 4);
                    }
                    break;

                case 0x0005: //总运行时长,秒
                    if (len == 4) {
                        isRunTimeValid = true;
                        runTime = ByteArrayToLong(sub_data, 0, 4);
                    }
                    break;

                case 0x0006://总熄火时长,秒
                    if (len == 4) {
                        isFlameOutValid = true;
                        flameOutDuration = ByteArrayToLong(sub_data, 0, 4);
                    }
                    break;

                case 0x0007://总怠速时长,秒
                    if (len == 4) {
                        isIdlingTimeValid = true;
                        idlingTime = ByteArrayToLong(sub_data, 0, 4);
                    }
                    break;

                case 0x0010: //加速度表
                    if (len > 4) {
                        isAccValid = true;
                        accCount = (int)ByteArrayToLong(sub_data, 0, 2);
                        accInterval = (int)ByteArrayToLong(sub_data, 2, 2);
                    }

                    if(accCount > 0 && len == 6 + accCount * 2){
                        accMaxValue = (int)ByteArrayToLong(sub_data, 4 + accCount * 2, 2);
                        accValue =  new int[accCount];
                        for(int j = 0; j < accCount; ++j)
                        {
                            accValue[j] = (int)ByteArrayToLong(sub_data, 4 + j * 2, 2);
                        }
                    }
                    break;

                case 0x0011://车辆状态表
//                    if (len == 20) { }
                    break;

                default: break;
            }
        }

        //
        mIsValid = true;

        mIsMileageValid = isMileageValid;
        mMileageType = mileageType;
        mMileageValue = mileageValue;

        mIsOilConsumptionValid = isOilConsumptionValid;
        mOilConsumptionType = oilConsumptionType;
        mOilConsumptionValue = oilConsumptionValue;

        mIsRunTimeValid = isRunTimeValid;
        mRunTime = runTime;
        mIsFlameOutValid = isFlameOutValid;
        mFlameOutDuration = flameOutDuration;
        mIsIdlingTimeValid = isIdlingTimeValid;
        mIdlingTime = idlingTime;

        mIsAccValid = isAccValid;
        mAccCount = accCount;
        mAccInterval = accInterval;
        mAccMaxValue = accMaxValue;
        mAccValue = accValue;
    }


    /***
     * 拆分扩展信息的数据
     * @param data 位置信息数据
     * @return 返回经过拆分处理的数据
     */
    private ArrayList<byte[]> DataSplitting(byte[] data) {
        ArrayList<byte[]> ret = new ArrayList<>();

        int sub_index = 0;
        while(true)
        {
            if(sub_index + 3 > data.length )
                break;

            //0-1:子类型; 2:子类型长度
            int sub_len  = (int)ByteArrayToLong(data, sub_index + 2, 1);   //子类型长度
            int new_index = sub_index + sub_len + 3;

            if(new_index > data.length)
                break;

            byte[] _tep = new byte[sub_len + 3];
            System.arraycopy(data, sub_index, _tep, 0, _tep.length);
            ret.add(_tep);

            sub_index = new_index;
        }

        return  ret;
    }
    public static long ByteArrayToLong(byte[] data, int index ,int len) {
        if(index < 0 || len <= 0 || index >= data.length || len + index > data.length)
            return  0;

        //
        long ret = (data[index] & 0xff);
        for(int i = 1; i < len; ++i)
        {
            ret = (ret << 8)  + (data[i + index] & 0xff);
        }

        return  ret;
    }

}
